package org.niux.AutoLoginQQ.operate;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.List;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.util.EntityUtils;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.widgets.Display;
import org.niux.AutoLoginQQ.VO.QQNumVO;
import org.niux.AutoLoginQQ.common.Constant;
import org.niux.AutoLoginQQ.ui.Main;
import org.niux.AutoLoginQQ.util.EncodeQQPass;


/**
 * 
 * 
 * Copyright (c) 2009,niux<br>
 * All rights reserved.<br>
 * 
 * 文件名称：ModifyInfo.java<br>
 * 摘 要：登录QQ操作类<br>
 * <br>
 * 当前版本：<br>
 * 作 者：mingxian Email: <a href="mailto:liangmingxian@gmail.com">liangmingxian@gmail.com</a><br>
 * 完成日期：@since 2012-9-13<br>
 * <br>
 * 取代版本：<br>
 * 原作者 ：<br>
 * 完成日期：@since 2012-9-13<br>
 */
public class ModifyInfo {
	
	private Log log = LogFactory.getLog(this.getClass());
//	private Main gui;
	private String verifyCode;
	
	public ModifyInfo(Main gui) {
		super();
//		this.gui = gui;
	}

	public void modifyPassword(String qqNum, String newPassword){
		
		log.debug("修改QQ：：" + qqNum + "的密码");
		
		QQNumVO qq = Constant.QQ_LIST.get(qqNum);
		
		HttpClient httpclient = new DefaultHttpClient();
		
		//配置https
		TrustManager easyTrustManager = new X509TrustManager() {
			
			@Override
			public X509Certificate[] getAcceptedIssuers() {
				 return new java.security.cert.X509Certificate[0];
			}
			
			@Override
			public void checkServerTrusted(X509Certificate[] arg0, String arg1)
					throws CertificateException {
			}
			
			@Override
			public void checkClientTrusted(X509Certificate[] arg0, String arg1)
					throws CertificateException {
			}
		};
		
		try {
			SSLContext sslContext = SSLContext.getInstance("TLS");
			sslContext.init(null, new TrustManager[]{easyTrustManager}, null);
			SSLSocketFactory sf = new SSLSocketFactory(sslContext);
			Scheme sch = new Scheme("https", 443, sf);
			httpclient.getConnectionManager().getSchemeRegistry().register(sch);
			
			// 发送判断是否需要验证码的请求
			String responseString = checkVerifyCode(httpclient,qqNum);
			
			log.debug(responseString);
			
			boolean isNeedVerifyCode = isNeedVerifyCode(responseString);
			
			// 截取返回的第二个和第三个参数，密码加密用到
			String secondParam = responseString.split(",")[1].replace("'", "");
			String thirdParam = responseString.split(",")[2].replace("'", "")
						.replace(")", "").replace(";", "");
			
			if (isNeedVerifyCode){
				log.debug("获取验证码");
				ImageData verifyCodeImage = getVerifyCode(httpclient,qqNum);
				log.debug("已经获取到验证码图片");

				// 打开验证码输入框
				showVerifyCode(qqNum, verifyCodeImage);
				
				// 等待用户输入
				while (verifyCode == null) {
					// 空循环等待输入
				}
				
				if("".equals(verifyCode)){
					alert("没有输入验证码");
					verifyCode = null;
					return;
				}
				
				secondParam = verifyCode;
				
				log.debug("输入的验证码是：" + verifyCode);
			}
			
			responseString = firstLogin(httpclient, qq, secondParam,thirdParam);

			log.debug(responseString);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 
	 * 方法概述：发送请求判断是否需要验证码 
	 * 描述：发送请求判断是否需要验证码
	 * 
	 * @param httpclient
	 * @param qqNum
	 * @return 
	 * 返回类型：String 
	 * 修改人：梁铭显 
	 * 修改时间：2012-9-9
	 */
	public String checkVerifyCode(HttpClient httpclient, String qqNum) {

		log.debug("发送判断是否需要验证码的请求");

		// 创建httpget.
		HttpGet httpget = new HttpGet("https://ssl.ptlogin2.qq.com/check?uin="
				+ qqNum + "&appid=1000801&r=0.2466624827781071");

		// 设置http头信息
		httpget.setHeader("Accept", "*/*");
		httpget.setHeader("Accept-Encoding", "gzip, deflate");
		httpget.setHeader("Accept-Language", "zh-cn");
		httpget.setHeader("Connection", "Keep-Alive");
		httpget.setHeader("Host", "ssl.ptlogin2.qq.com");
		httpget.setHeader("Referer", "https://ui.ptlogin2.qq.com/cgi-bin/login?" +
				"appid=1000801&s_url=https%3A//password.qq.com/cgi-bin/chs/dj_redirect%3Fw%3D1&" +
				"f_url=loginerroralert&hide_close_icon=1");
		httpget.setHeader("User-Agent",
				"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)");

		// 设置Cookies
		BasicClientCookie chkuin = new BasicClientCookie("chkuin", qqNum);
		chkuin.setDomain(".ptlogin2.qq.com");
		chkuin.setPath("/");
		
		BasicClientCookie uikey = new BasicClientCookie("uikey",
				"f3621cb34dcbcd77887e13c3bbd638515fef6b015aa57c2f46d6722b90c86e08");
		uikey.setDomain(".ptlogin2.qq.com");
		uikey.setPath("/");

		((AbstractHttpClient) httpclient).getCookieStore().addCookie(chkuin);
		((AbstractHttpClient) httpclient).getCookieStore().addCookie(uikey);

		String responseString = "";

		try {
			HttpResponse response = httpclient.execute(httpget);

			// 获取响应实
			HttpEntity entity = response.getEntity();

			responseString = EntityUtils.toString(entity);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return responseString;
	}
	
	/**
	 * 
	 * 方法概述：判断是否需要验证码 
	 * 描述：判断是否需要验证码
	 * 
	 * @param responseString
	 * @return 
	 * 返回类型：boolean 
	 * 修改人：梁铭显 
	 * 修改时间：2012-9-9
	 */
	public boolean isNeedVerifyCode(String responseString) {
		log.debug("判断是否需要验证码");
		// 判断是否需要验证码
		// ptui_checkVC('0','!8Z3','\x00\x00\x00\x00\x18\xc4\x46\x0e');这种返回格式是不需要验证码
		// ptui_checkVC('1','6eca383c5c31537b6dbb2258ea5cc9bf49ab51677128db2b','\x00\x00\x00\x00\x01\xf0\xbb\xec');
		// 这种返回格式需要验证码
		if (responseString.contains("ptui_checkVC('0'")) {// 不需要验证码
			log.debug("不需要验证码");
			return false;
		} else { // 需要验证码
			log.debug("需要验证码");
			return true;
		}
	}
	
	/**
	 * 
	 * 方法概述：获取验证码图片数据 
	 * 描述：获取验证码图片数据
	 * 
	 * @param httpclient
	 * @param qqNum
	 * @return 
	 * 返回类型：ImageData 
	 * 修改人：梁铭显 
	 * 修改时间：2012-9-9
	 */
	public ImageData getVerifyCode(HttpClient httpclient, String qqNum) {

		log.debug("获取验证码图片数据");

		HttpGet httpget = new HttpGet(
				"https://ssl.captcha.qq.com/getimage?aid=1000801&r=0.2466624827781071&uin="
						+ qqNum);

		// 设置http头信息
		httpget.setHeader("Accept", "*/*");
		httpget.setHeader("Accept-Encoding", "gzip, deflate");
		httpget.setHeader("Accept-Language", "zh-cn");
		httpget.setHeader("Connection", "Keep-Alive");
		httpget.setHeader("Host", "ssl.ptlogin2.qq.com");
		httpget.setHeader("Referer", "https://ui.ptlogin2.qq.com/cgi-bin/login?appid=1000801&" +
				"s_url=https%3A//password.qq.com/cgi-bin/chs/dj_redirect%3Fw%3D1&" +
				"f_url=loginerroralert&hide_close_icon=1");
		httpget.setHeader("User-Agent",
				"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)");

		ImageData[] imageDatas = null;

		try {
			HttpResponse response = httpclient.execute(httpget);
			
			// 获取响应实
			HttpEntity entity = response.getEntity();
			
			// 构建验证码图片
			ImageLoader loader = new ImageLoader();
			imageDatas = loader.load(entity.getContent());

		} catch (Exception e) {
			e.printStackTrace();
		}

		return imageDatas[0];
	}
	
	/**
	 * 
	 * 方法概述：第一次登录操作 
	 * 描述：第一次登录操作
	 * 
	 * @param HttpClient httpclient
	 * @param QQNumVO qq
	 * @param String verifycode
	 * @param String encodeKey
	 * @return 
	 * 返回类型：ImageData 
	 * 修改人：梁铭显 
	 * 修改时间：2012-9-9
	 */
	@SuppressWarnings("static-access")
	public String firstLogin(HttpClient httpclient, QQNumVO qq,
			String verifycode, String encodeKey) {
		log.debug("第一次登录操作");

		// 加密QQ密码
		EncodeQQPass encodeQQPass = new EncodeQQPass();

		String p = encodeQQPass.encodePass(qq.getPassword(), verifycode,
				encodeKey);
		
		log.debug(p);

		HttpGet httpget = new HttpGet("https://ssl.ptlogin2.qq.com/login?u="+qq.getQqNum()+
				"&p="+p+
				"&verifycode="+verifycode+
				"&aid=1000801&" +
				"u1=https%3A%2F%2Fpassword.qq.com%2Fcgi-bin%2Fchs%2Fdj_redirect%3Fw%3D1&h=1&ptredirect=1" +
				"&ptlang=2052&from_ui=1&dumy=&fp=loginerroralert&action=3-7-45406&mibao_css=&t=1&g=1");

		// 设置http头信息
		httpget.setHeader("Accept", "*/*");
		httpget.setHeader("Accept-Encoding", "gzip, deflate");
		httpget.setHeader("Accept-Language", "zh-cn");
		httpget.setHeader("Connection", "Keep-Alive");
		httpget.setHeader("Host", "ssl.ptlogin2.qq.com");
		httpget.setHeader("Referer", "https://ui.ptlogin2.qq.com/cgi-bin/login?appid=1000801&" +
				"s_url=https%3A//password.qq.com/cgi-bin/chs/dj_redirect%3Fw%3D1&f_url=loginerroralert&hide_close_icon=1");
		httpget.setHeader("User-Agent",
				"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)");
		
		log.debug("======访问前=======");

		// 获取cookies
		List<Cookie> cookies = ((AbstractHttpClient) httpclient).getCookieStore()
				.getCookies();

		for (int i = 0; i < cookies.size(); i++) {
			log.debug("- " + cookies.get(i).toString());
		}

		log.debug("======访问前=======");

		String responseString = "";

		try {
			HttpResponse response = httpclient.execute(httpget);

			// 获取响应实
			HttpEntity entity = response.getEntity();

			responseString = EntityUtils.toString(entity);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return responseString;
	}

	/**
	 * 
	 * 方法概述：打开验证码输入框
	 * 描述：打开验证码输入框
	 * @param qqNum
	 * @param imageData
	 * 返回类型：void
	 * 修改人：梁铭显
	 * 修改时间：2012-9-10
	 */
	public void showVerifyCode(final String qqNum, final ImageData imageData) {
		Display.getDefault().asyncExec(new Runnable() {
			public void run() {
				log.debug("========================================");
//				verifyCode = gui.showVerifyCode(qqNum, imageData);
			}
		});
	}
	
	/**
	 * 
	 * 方法概述：提示信息对话框
	 * 描述：提示信息对话框
	 * @param info
	 * 返回类型：void
	 * 修改人：梁铭显
	 * 修改时间：2012-9-8
	 */
	public void alert(final String info){
		Display.getDefault().asyncExec(new Runnable() {
			public void run() {
				alert(info);
			}
		});
	}
}
